package com.smart.community.property.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.property.dto.RepairOrderWorkDTO;
import com.smart.community.property.entity.RepairOrder;
import com.smart.community.property.mapper.RepairOrderMapper;
import com.smart.community.property.service.IRepairOrderWorkService;
import com.smart.community.property.vo.RepairOrderWorkVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 维修工单工作管理扩展服务实现类
 *
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RepairOrderWorkServiceImpl extends ServiceImpl<RepairOrderMapper, RepairOrder> implements IRepairOrderWorkService {

    private final RepairOrderMapper repairOrderMapper;

    @Override
    @Cacheable(value = "repair_order_work:page", key = "#current + '_' + #size + '_' + (#params != null ? #params.hashCode() : 'null')")
    public IPage<RepairOrderWorkVO> getRepairOrderWorkPage(Integer current, Integer size, Map<String, Object> params) {
        log.info("分页查询维修工单（工作管理扩展），当前页：{}，每页大小：{}，查询参数：{}", current, size, params);
        
        Page<RepairOrderWorkVO> page = new Page<>(current, size);
        // 这里需要实现具体的分页查询逻辑
        // 由于RepairOrderMapper可能没有对应的方法，这里先返回空结果
        return page;
    }

    @Override
    @Cacheable(value = "repair_order_work:detail", key = "#id")
    public RepairOrderWorkVO getRepairOrderWorkById(Long id) {
        log.info("根据ID查询维修工单详情（工作管理扩展），ID：{}", id);
        
        RepairOrder repairOrder = getById(id);
        if (repairOrder == null) {
            return null;
        }
        
        return convertToWorkVO(repairOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public boolean addRepairOrderWork(RepairOrderWorkDTO repairOrderWorkDTO) {
        log.info("新增维修工单（工作管理扩展），标题：{}，维修类型：{}", 
                repairOrderWorkDTO.getTitle(), repairOrderWorkDTO.getRepairType());
        
        RepairOrder repairOrder = convertToEntity(repairOrderWorkDTO);
        repairOrder.setCreateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setCreateTime(LocalDateTime.now());
        repairOrder.setUpdateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setUpdateTime(LocalDateTime.now());
        
        return save(repairOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public boolean updateRepairOrderWork(RepairOrderWorkDTO repairOrderWorkDTO) {
        log.info("更新维修工单（工作管理扩展），ID：{}，标题：{}", 
                repairOrderWorkDTO.getId(), repairOrderWorkDTO.getTitle());
        
        RepairOrder repairOrder = convertToEntity(repairOrderWorkDTO);
        repairOrder.setUpdateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setUpdateTime(LocalDateTime.now());
        
        return updateById(repairOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public boolean assignRepairOrder(Long orderId, Long repairmanId, String estimatedCompleteTime, String remark) {
        log.info("分配维修工单，工单ID：{}，维修人员ID：{}，预计完成时间：{}", orderId, repairmanId, estimatedCompleteTime);
        
        RepairOrder repairOrder = getById(orderId);
        if (repairOrder == null) {
            throw new RuntimeException("维修工单不存在");
        }
        
        repairOrder.setAssignTo(repairmanId);
        repairOrder.setAssignTime(LocalDateTime.now());
        repairOrder.setStatus(2); // 已分配状态
        repairOrder.setUpdateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setUpdateTime(LocalDateTime.now());
        
        return updateById(repairOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public Map<String, Integer> batchAssignRepairOrders(List<Long> orderIds, Long repairmanId, String estimatedCompleteTime) {
        log.info("批量分配维修工单，工单IDs：{}，维修人员ID：{}，预计完成时间：{}", orderIds, repairmanId, estimatedCompleteTime);
        
        Map<String, Integer> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        
        for (Long orderId : orderIds) {
            try {
                if (assignRepairOrder(orderId, repairmanId, estimatedCompleteTime, "批量分配")) {
                    successCount++;
                } else {
                    failCount++;
                }
            } catch (Exception e) {
                log.error("分配工单失败，工单ID：{}，错误：{}", orderId, e.getMessage());
                failCount++;
            }
        }
        
        result.put("successCount", successCount);
        result.put("failCount", failCount);
        result.put("totalCount", orderIds.size());
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public boolean startRepair(Long orderId, List<String> materialList, String remark) {
        log.info("开始维修，工单ID：{}，材料清单：{}", orderId, materialList);
        
        RepairOrder repairOrder = getById(orderId);
        if (repairOrder == null) {
            throw new RuntimeException("维修工单不存在");
        }
        
        repairOrder.setStatus(3); // 维修中状态
        repairOrder.setUpdateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setUpdateTime(LocalDateTime.now());
        
        return updateById(repairOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public boolean completeRepair(Long orderId, String repairResult, String repairCost, String workHours, String remark) {
        log.info("完成维修，工单ID：{}，维修结果：{}，维修费用：{}，工时：{}", orderId, repairResult, repairCost, workHours);
        
        RepairOrder repairOrder = getById(orderId);
        if (repairOrder == null) {
            throw new RuntimeException("维修工单不存在");
        }
        
        repairOrder.setStatus(4); // 已完成状态
        repairOrder.setCompleteTime(LocalDateTime.now());
        repairOrder.setUpdateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setUpdateTime(LocalDateTime.now());
        
        return updateById(repairOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "repair_order_work:page", "repair_order_work:detail", "repair_order_work:repairman", 
        "repair_order_work:urgent", "repair_order_work:timeout", "repair_order_work:statistics"
    }, allEntries = true)
    public boolean submitCustomerRating(Long orderId, Integer satisfaction, String comment) {
        log.info("提交客户评价，工单ID：{}，满意度：{}，评价：{}", orderId, satisfaction, comment);
        
        RepairOrder repairOrder = getById(orderId);
        if (repairOrder == null) {
            throw new RuntimeException("维修工单不存在");
        }
        
        repairOrder.setSatisfaction(satisfaction);
        repairOrder.setUpdateBy(SecurityUtils.getCurrentUserId());
        repairOrder.setUpdateTime(LocalDateTime.now());
        
        return updateById(repairOrder);
    }

    @Override
    @Cacheable(value = "repair_order_work:repairman", key = "#repairmanId + '_' + #propertyCompanyId + '_' + #status")
    public List<RepairOrderWorkVO> getRepairOrdersByRepairman(Long repairmanId, Long propertyCompanyId, Integer status) {
        log.info("查询维修人员工单，维修人员ID：{}，物业公司ID：{}，状态：{}", repairmanId, propertyCompanyId, status);
        
        LambdaQueryWrapper<RepairOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RepairOrder::getAssignTo, repairmanId);
        if (status != null) {
            queryWrapper.eq(RepairOrder::getStatus, status);
        }
        queryWrapper.orderByDesc(RepairOrder::getCreateTime);
        
        List<RepairOrder> repairOrders = list(queryWrapper);
        return repairOrders.stream()
                .map(this::convertToWorkVO)
                .collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = "repair_order_work:urgent", key = "#propertyCompanyId")
    public List<RepairOrderWorkVO> getUrgentRepairOrders(Long propertyCompanyId) {
        log.info("查询紧急工单，物业公司ID：{}", propertyCompanyId);
        
        LambdaQueryWrapper<RepairOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RepairOrder::getUrgencyLevel, 3); // 紧急级别
        queryWrapper.in(RepairOrder::getStatus, Arrays.asList(1, 2, 3)); // 待处理、已分配、维修中
        queryWrapper.orderByDesc(RepairOrder::getCreateTime);
        
        List<RepairOrder> repairOrders = list(queryWrapper);
        return repairOrders.stream()
                .map(this::convertToWorkVO)
                .collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = "repair_order_work:timeout", key = "#propertyCompanyId + '_' + #timeoutHours")
    public List<RepairOrderWorkVO> getTimeoutRepairOrders(Long propertyCompanyId, Integer timeoutHours) {
        log.info("查询超时工单，物业公司ID：{}，超时小时数：{}", propertyCompanyId, timeoutHours);
        
        LocalDateTime timeoutThreshold = LocalDateTime.now().minusHours(timeoutHours);
        
        LambdaQueryWrapper<RepairOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RepairOrder::getStatus, Arrays.asList(1, 2, 3)); // 待处理、已分配、维修中
        queryWrapper.lt(RepairOrder::getCreateTime, timeoutThreshold);
        queryWrapper.orderByDesc(RepairOrder::getCreateTime);
        
        List<RepairOrder> repairOrders = list(queryWrapper);
        return repairOrders.stream()
                .map(this::convertToWorkVO)
                .collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = "repair_order_work:statistics", key = "#propertyCompanyId + '_' + #startDate + '_' + #endDate")
    public Map<String, Object> getRepairOrderWorkStatistics(Long propertyCompanyId, LocalDate startDate, LocalDate endDate) {
        log.info("查询维修工单统计信息，物业公司ID：{}，开始日期：{}，结束日期：{}", propertyCompanyId, startDate, endDate);
        
        Map<String, Object> statistics = new HashMap<>();
        
        // 这里需要实现具体的统计逻辑
        // 由于RepairOrderMapper可能没有对应的方法，这里先返回模拟数据
        statistics.put("totalCount", 0);
        statistics.put("pendingCount", 0);
        statistics.put("inProgressCount", 0);
        statistics.put("completedCount", 0);
        statistics.put("cancelledCount", 0);
        statistics.put("averageProcessingTime", 0.0);
        statistics.put("customerSatisfaction", 0.0);
        
        return statistics;
    }

    @Override
    @Cacheable(value = "repair_order_work:sources", key = "'all'")
    public List<Map<String, Object>> getRepairOrderSourceList() {
        log.info("获取工单来源列表");
        
        List<Map<String, Object>> sources = new ArrayList<>();
        sources.add(createSourceMap(1, "业主报修"));
        sources.add(createSourceMap(2, "物业巡查"));
        sources.add(createSourceMap(3, "设备报警"));
        sources.add(createSourceMap(4, "客服转接"));
        sources.add(createSourceMap(5, "其他"));
        
        return sources;
    }

    @Override
    @Cacheable(value = "repair_order_work:categories", key = "'all'")
    public List<Map<String, Object>> getRepairOrderCategoryList() {
        log.info("获取工单分类列表");
        
        List<Map<String, Object>> categories = new ArrayList<>();
        categories.add(createCategoryMap(1, "设备维修"));
        categories.add(createCategoryMap(2, "水电维修"));
        categories.add(createCategoryMap(3, "门窗维修"));
        categories.add(createCategoryMap(4, "电梯维修"));
        categories.add(createCategoryMap(5, "其他"));
        
        return categories;
    }

    @Override
    @Cacheable(value = "repair_order_work:notification_methods", key = "'all'")
    public List<Map<String, Object>> getNotificationMethodList() {
        log.info("获取通知方式列表");
        
        List<Map<String, Object>> methods = new ArrayList<>();
        methods.add(createMethodMap(1, "电话通知"));
        methods.add(createMethodMap(2, "短信通知"));
        methods.add(createMethodMap(3, "微信通知"));
        methods.add(createMethodMap(4, "上门通知"));
        methods.add(createMethodMap(5, "其他"));
        
        return methods;
    }

    // 其他方法的实现...
    @Override
    public List<RepairOrderWorkVO> getPendingAssignRepairOrders(Long propertyCompanyId) {
        // 实现待分配工单查询
        return new ArrayList<>();
    }

    @Override
    public List<RepairOrderWorkVO> getInProgressRepairOrders(Long propertyCompanyId) {
        // 实现进行中工单查询
        return new ArrayList<>();
    }

    @Override
    public List<RepairOrderWorkVO> getCompletedRepairOrders(Long propertyCompanyId, LocalDate startDate, LocalDate endDate) {
        // 实现已完成工单查询
        return new ArrayList<>();
    }

    @Override
    public Map<String, Object> getRepairmanWorkloadStatistics(Long repairmanId, Long propertyCompanyId, LocalDate startDate, LocalDate endDate) {
        // 实现维修人员工作量统计
        return new HashMap<>();
    }

    @Override
    public Map<String, Object> getRepairOrderTypeStatistics(Long propertyCompanyId, LocalDate startDate, LocalDate endDate) {
        // 实现工单类型统计
        return new HashMap<>();
    }

    @Override
    public Map<String, Object> getCustomerSatisfactionStatistics(Long propertyCompanyId, LocalDate startDate, LocalDate endDate) {
        // 实现客户满意度统计
        return new HashMap<>();
    }

    @Override
    public boolean setFollowUp(Long orderId, String followUpTime, String remark) {
        // 实现设置回访
        return true;
    }

    @Override
    public boolean completeFollowUp(Long orderId, String followUpResult) {
        // 实现完成回访
        return true;
    }

    @Override
    public boolean notifyCustomer(Long orderId, Integer notificationMethod, String content) {
        // 实现通知客户
        return true;
    }

    /**
     * 转换DTO为实体
     */
    private RepairOrder convertToEntity(RepairOrderWorkDTO dto) {
        RepairOrder repairOrder = new RepairOrder();
        repairOrder.setId(dto.getId());
        repairOrder.setOrderNo(dto.getOrderNo());
        repairOrder.setTitle(dto.getTitle());
        repairOrder.setDescription(dto.getDescription());
        repairOrder.setUserId(dto.getUserId());
        repairOrder.setResidentId(dto.getHouseholdId()); // 使用householdId
        repairOrder.setCommunityId(dto.getCommunityId());
        repairOrder.setRepairType(dto.getRepairType());
        repairOrder.setPriority(dto.getUrgencyLevel()); // 使用urgencyLevel作为priority
        repairOrder.setUrgencyLevel(dto.getUrgencyLevel());
        repairOrder.setStatus(dto.getStatus());
        repairOrder.setLocation(dto.getRepairAddress()); // 使用repairAddress作为location
        repairOrder.setRepairImages(dto.getImageList() != null ? String.join(",", dto.getImageList()) : null);
        repairOrder.setRepairAddress(dto.getRepairAddress());
        repairOrder.setContactPhone(dto.getContactPhone());
        repairOrder.setAssignTo(dto.getAssignTo());
        repairOrder.setAssignTime(dto.getAcceptTime());
        repairOrder.setCompleteTime(dto.getCompleteTime());
        repairOrder.setSatisfaction(dto.getSatisfactionScore());
        return repairOrder;
    }

    /**
     * 转换实体为VO
     */
    private RepairOrderWorkVO convertToWorkVO(RepairOrder repairOrder) {
        RepairOrderWorkVO vo = new RepairOrderWorkVO();
        vo.setId(repairOrder.getId());
        vo.setOrderNo(repairOrder.getOrderNo());
        vo.setTitle(repairOrder.getTitle());
        vo.setDescription(repairOrder.getDescription());
        vo.setUserId(repairOrder.getUserId());
        vo.setHouseholdId(repairOrder.getResidentId()); // 使用residentId作为householdId
        vo.setCommunityId(repairOrder.getCommunityId());
        vo.setRepairType(repairOrder.getRepairType());
        vo.setUrgencyLevel(repairOrder.getUrgencyLevel());
        vo.setStatus(repairOrder.getStatus());
        vo.setRepairAddress(repairOrder.getRepairAddress());
        vo.setRepairImages(repairOrder.getRepairImages());
        vo.setContactPhone(repairOrder.getContactPhone());
        vo.setRepairmanId(repairOrder.getAssignTo());
        vo.setAcceptTime(repairOrder.getAssignTime());
        vo.setCompletionTime(repairOrder.getCompleteTime());
        vo.setSatisfactionScore(repairOrder.getSatisfaction());
        vo.setCreateTime(repairOrder.getCreateTime());
        vo.setUpdateTime(repairOrder.getUpdateTime());
        
        // 设置扩展字段的默认值
        vo.setCanAssign(true);
        vo.setCanComplete(false);
        vo.setCanCancel(true);
        vo.setCanRate(false);
        vo.setCanFollowUp(false);
        
        return vo;
    }

    /**
     * 创建来源映射
     */
    private Map<String, Object> createSourceMap(Integer code, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("name", name);
        return map;
    }

    /**
     * 创建分类映射
     */
    private Map<String, Object> createCategoryMap(Integer code, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("name", name);
        return map;
    }

    /**
     * 创建方法映射
     */
    private Map<String, Object> createMethodMap(Integer code, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("name", name);
        return map;
    }
}
